package com.marui.ch8a.marui;

import com.marui.ch8a.marui.vo.MITaskProcesser;
import com.marui.ch8a.marui.vo.MJobInfo;
import com.marui.ch8a.marui.vo.MTaskResult;
import com.marui.ch8a.marui.vo.MTaskResultType;

import java.util.concurrent.*;

/**
 * 主体类
 */
public class MPedingJobPool {
    //保守估计
    private static final int THREAD_COUNTS=Runtime.getRuntime().availableProcessors();
    // 任务队列
    private static BlockingQueue<Runnable> taskQueue = new ArrayBlockingQueue<>(5000);
    //线程池，固定大小，有界队列
    private static ExecutorService taskExecutor = new ThreadPoolExecutor(THREAD_COUNTS, THREAD_COUNTS, 60,
            TimeUnit.SECONDS, taskQueue);
    // job存放的容器
    private static ConcurrentHashMap<String, MJobInfo<?>> jobInfoMap = new  ConcurrentHashMap<>();
   /* private static MCheckJobProcesser checkJob
            = MCheckJobProcesser.getInstance();*/

    // 单例模式
    private MPedingJobPool(){
    }

    private static class MJobPoolHolder{
        public static MPedingJobPool pool = new MPedingJobPool();
    }

    public static MPedingJobPool getInstance() {
        return MPedingJobPool.MJobPoolHolder.pool;
    }

    //对工作中的任务进行包装，提交给线程池使用，并处理任务的结果，写入缓存以供查询
    private static class MPendingTask<T,R> implements Runnable{
        private MJobInfo<R> jobInfo;
        private T processData;

        public MPendingTask(MJobInfo<R> jobInfo, T processData) {
            this.jobInfo = jobInfo;
            this.processData = processData;
        }

        @Override
        public void run() {
            {
                R r = null;
                MITaskProcesser<T,R> taskProcesser =
                        (MITaskProcesser<T, R>) jobInfo.getTaskProcesser();
                MTaskResult<R> result = null;

                try {
                    //调用业务人员实现的具体方法
                    result = taskProcesser.taskExecute(processData);
                    //要做检查，防止开发人员处理不当
                    if (result == null) {
                        result = new MTaskResult<R>(MTaskResultType.EXCEPTION, r,
                                "result is null");
                    }
                    if (result.getmTaskResultType() == null) {
                        if (result.getReason() == null) {
                            result = new MTaskResult<R>(MTaskResultType.EXCEPTION, r, "reason is null");
                        } else {
                            result = new MTaskResult<R>(MTaskResultType.EXCEPTION, r,
                                    "result is null,but reason:" + result.getReason());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    result = new MTaskResult<R>(MTaskResultType.EXCEPTION, r,
                            e.getMessage());
                }finally {
                    // jobInfo.addTaskResult(result,null);
                }
            }

        }
    }
    //根据工作名称检索工作
    @SuppressWarnings("unchecked")
    private <R> MJobInfo<R> getJob(String jobName){
        MJobInfo<R> jobInfo = (MJobInfo<R>) jobInfoMap.get(jobName);
        if(null==jobInfo) {
            throw new RuntimeException(jobName+"是个非法任务。");
        }
        return jobInfo;
    }

    //调用者提交工作中的任务
    public <T,R> void putTask(String jobName,T t){
        MJobInfo<R> jobInfo = getJob(jobName);
        MPendingTask<T,R> task = new MPendingTask<T,R>(jobInfo, t);
        taskExecutor.execute(task);
    }


    public  <R> void registerJob(String jobName, int jobLength,
                                 MITaskProcesser<?, ?> taskProcesser, long expireTime){
        MJobInfo<R> jobInfo = new MJobInfo(jobName,jobLength,taskProcesser,expireTime);
        if(jobInfoMap.putIfAbsent(jobName,jobInfo)!=null){
            throw new RuntimeException(jobName+"已经注册了！");
        }
    }
}
